package common.util;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;

import java.math.BigDecimal;
import java.util.*;

public class StfUtil {


    public static String reStr(String text) {
        SingletonLemma instance = SingletonLemma.getInstance();
        StanfordCoreNLP pipeline = instance.getPipeline();
        if (text.length() < 3) {
            return text;
        }
        StringBuilder lemma = new StringBuilder();
        Properties properties = new Properties();
        //分词、分句、词性标注和次元信息。
        properties.put("annotators", "tokenize,ssplit,pos,lemma");
        Annotation document = new Annotation(text);
        pipeline.annotate(document);
        List<CoreMap> words = document.get(CoreAnnotations.SentencesAnnotation.class);
        for (CoreMap wordTemp : words) {
            for (CoreLabel token : wordTemp.get(CoreAnnotations.TokensAnnotation.class)) {
                String originalWord = token.get(CoreAnnotations.LemmaAnnotation.class);
                lemma.append(" ").append(originalWord);
            }
        }

        return reLemma(lemma.toString()).toLowerCase().replace(".", " ").replace(",", " ").replace(":", " ").replace("'", " ").replace("?", " ").replaceAll(" +", " ").trim();
    }

    // 因为斯坦福会对标点符号前后加上空格，因此，需要作一定的处理。比如：ganoderma lucidum ( leyss . ex fr . ) karst -> ganoderma lucidum (leyss.ex fr) karst
    public static String reLemma(String str) {
        str = str.replace(" / ", "/")
                .replace(" , ", ",")
                .replace(" ' ", "'")
                .replace(" '", "'")
                .replace(" + ", "+")
                .replace(" ; ", ";")
                .replace(" ;", ";")
                .replace(" ^ ", "^")
                .replace(" ] ", "] ")
                .replace(" } ", "} ")
                .replace(" [ ", " [")
                .replace(" { ", " {")
                .replace(" \\ ", "\\")
                .replace(" : ", ":")
                .replace(" $ ", " $")
                .replace(" % ", "% ")
                .replace(" # ", "#")
                .replace(" #", "#")
                .replace(" - ", "-")
                .replace(" . ", ".")
                .replace("( ", "(")
                .replace(" )", ")")
                .replace("()", " ")
                .replace(".)", ")")
                .replaceAll(" +", " ").trim();
        // 因为斯坦福会对引号前后加上引号，因此需要还原。比如：ch " ildren's hos " pi " t " al -> ch "ildren's hos" pi "t" al
        if (str.contains("\"")) {
            List<String> list = Arrays.asList(str.split("\""));
            StringBuilder temp = new StringBuilder();
            for (int i = 0; i < list.size(); i++) {
                if (i % 2 == 0) {
                    temp.append(list.get(i).trim()).append(" \"");
                } else {
                    temp.append(list.get(i).trim()).append("\" ");
                }
            }
            if (!str.endsWith("\"") && temp.toString().endsWith("\"")) {
                temp = new StringBuilder(temp.substring(0, temp.length() - "\"".length()));
            }
            str = temp.toString().trim();
        }
        return str.trim();
    }


    /**
     * 自定义评分
     *
     * @param searchTerms 检索词
     * @param hitWords    命中词
     * @return
     */
    public static double genScore(String searchTerms, String hitWords) {
        String[] split = reStr(searchTerms).split(" ");
        String[] list = reStr(hitWords).split(" ");
        int sum = split.length + list.length;
        if (sum > 0) {
            Set<String> set = new HashSet<>(Arrays.asList(list));
            int num = 0;
            for (String s : split) {
                if (set.contains(s)) {
                    num += 2;
                }
            }
            BigDecimal d1 = BigDecimal.valueOf(num);
            BigDecimal d2 = BigDecimal.valueOf(sum);
            return d1.divide(d2, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return 0.0;
    }

    /**
     * 自定义相同数量词语百分比
     *
     * @param searchTerms 检索词
     * @param hitWords    命中词
     * @return
     */
    public static double genManualScore(String searchTerms, String hitWords) {
        String[] split = reStr(searchTerms).split(" ");
        String[] list = reStr(hitWords).split(" ");
        int sum = split.length;
        if (sum > 0) {
            Set<String> set = new HashSet<>(Arrays.asList(list));
            int num = 0;
            for (String s : split) {
                if (set.contains(s)) {
                    num++;
                }
            }
            BigDecimal d1 = BigDecimal.valueOf(num);
            BigDecimal d2 = BigDecimal.valueOf(sum);
            return d1.divide(d2, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return 0.0;
    }


}
